#!/usr/bin/env python

import gtk
import gtk.glade
import gtk.gdk
import pango 

import gnome.ui
import gnomevfs

import os

import uspCoreUtils
import utils.GConfigurator as uspGConfig
import utils.ButtonFactory as uspButtonFactory

from enteredTextParserAndExecutor import *

class AbstractPageView:
	def __init__(self, widgetTree, leftBoxName, rightBoxName):
		self.leftButtonBox = widgetTree.get_widget(leftBoxName)
		self.rightButtonBox = widgetTree.get_widget(rightBoxName)
		self.widgetTree = widgetTree
		
	def fill(self):
		self.fillLeftBox()
		self.fillRightBox()
	
	def fillLeftBox(self):
		pass
	
	def fillRightBox(self):
		pass 
	
	def update(self, text):
		pass
		
	def clear(self):
		clearWidgetChildren(self.leftButtonBox)
		clearWidgetChildren(self.rightButtonBox)
	
class AbstractCommonPageView(AbstractPageView):
	def __init__(self, widgetTree, leftBoxName, rightBoxName, menuFileName):
		AbstractPageView.__init__(self, widgetTree, leftBoxName, rightBoxName)
		self.currentCategory = 'All'
		self.menu = uspCoreUtils.XdgMenu(menuFileName)
		self.toolTips = gtk.Tooltips()
		self.dragging = False
	
	def showChild(self, child, text):
		if self.currentCategory == 'All' or self.menu.isEntryIn(child.key, self.currentCategory):
			return uspCoreUtils.textMatchesCriterions(text, child.criteria)
		return False
	
	def refreshRightBox(self):
		clearWidgetChildren(self.rightButtonBox)
		self.fillRightBox()
		
	def fillLeftBox(self):
		buttonFactory = uspButtonFactory.ButtonFactory()
		buttonFactory.iconSize = gtk.ICON_SIZE_BUTTON
		buttonFactory.clearLabelAttributes()
		buttonFactory.addLabelAttribute(pango.AttrWeight(pango.WEIGHT_NORMAL, 0, -1))
		buttonFactory.addEvent("button_release_event", self.categoryButtonClicked, 'All')
		buttonFactory.toolTipWidget = self.toolTips
		button = buttonFactory.create(['All'], '')
		self.leftButtonBox.pack_start(button)
		
		self.selectedButton = button
		button.set_relief(gtk.RELIEF_HALF)
		
		for category in self.menu.allCategories(): 
			buttonFactory.addEvent("button_release_event", self.categoryButtonClicked, category.getName())
			toolTipText = category.getName() 
			button = buttonFactory.create([category.getName()], category.getIcon(), toolTipText)
			self.leftButtonBox.pack_start(button)
	
	def fillRightBox(self): 
		buttonFactory = uspButtonFactory.ButtonFactory()
		buttonFactory.iconSize = gtk.ICON_SIZE_BUTTON
		buttonFactory.clearLabelAttributes()
		buttonFactory.addLabelAttribute(pango.AttrWeight(pango.WEIGHT_NORMAL, 0, -1))
		buttonFactory.addLabelAttribute(pango.AttrWeight(pango.WEIGHT_NORMAL, 0, -1))
		buttonFactory.toolTipWidget = self.toolTips
		buttonFactory.minLabelWidth = 20
		showGeneric = Configuration().applicationsGClient.getBoolean('showGenericName', True)
		
		for entry in self.menu.allEntries():
			buttonFactory.addEvent("button_release_event", self.entryButtonClicked, entry.DesktopEntry)
			if showGeneric:
				#labels = [entry.DesktopEntry.getName(), entry.DesktopEntry.getGenericName()]
				labels = [entry.DesktopEntry.getName()]
			else:
				labels = [entry.DesktopEntry.getName()]
			
			toolTipText  = "" if not entry.DesktopEntry.getName() else "Name: %s\n" % entry.DesktopEntry.getName()
			toolTipText += "" if not entry.DesktopEntry.getGenericName() else "Generic name: %s\n" % entry.DesktopEntry.getGenericName()
			toolTipText += "" if not entry.DesktopEntry.getComment() else "Comment: %s\n" % entry.DesktopEntry.getComment()
			toolTipText += "" if not entry.DesktopEntry.getExec() else "Exec: %s" % entry.DesktopEntry.getExec()
			
			desktopEntry = entry.DesktopEntry
			button = buttonFactory.create(labels, desktopEntry.getIcon(), toolTipText)
			button.key = desktopEntry.getName()
			
			# Generally for sorting
			button.criteria = [
				desktopEntry.getName(), 
				desktopEntry.getGenericName(), 
				desktopEntry.getComment(), 
				desktopEntry.getExec()]
			
			#D'N'D
			targets = [( "text/uri-list", 0, 0 )]
			button.connect("drag-data-get", self.dragDataSend, gnomevfs.get_uri_from_local_path(desktopEntry.getFileName()))
			button.connect("drag-end", self.dragEnd)
			button.connect("drag-begin", self.dragBegin)
			button.drag_source_set(gtk.gdk.BUTTON1_MASK, targets, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
			
			self.rightButtonBox.pack_start(button)
	
	def dragDataSend(self, widget, context, selection, targetType, eventTime, fileUri):
		selection.set_uris([fileUri])
	
	def dragBegin(self, widget, drag_context):
		self.dragging = True
		
	def dragEnd(self, widget, drag_context):
		self.dragging = False
	
	def update(self, text):
		self.text = text
		for child in self.rightButtonBox.get_children():
			if self.showChild(child, text):
				child.show()
			else:
				child.hide()
				
	def categoryButtonClicked(self, widget, event, category):
		self.currentCategory = category
		self.update(self.text)
		widget.set_relief(gtk.RELIEF_HALF)
		if hasattr(self, "selectedButton"):
			self.selectedButton.set_relief( gtk.RELIEF_NONE )
		self.selectedButton = widget
		
	def entryButtonClicked(self, widget, event, desktopEntry):
		if self.dragging:
			return
		if event.button == 1:
			recentManager = gtk.recent_manager_get_default()
			recentManager.add_item(gnomevfs.get_uri_from_local_path(desktopEntry.getFileName()))
			self.executeApplication(desktopEntry.getExec())
			Configuration().hideView()
		
	def executeApplication(self, executeString):
		executeArgs = uspCoreUtils.removeArgs(executeString.split())
		uspCoreUtils.execute(executeArgs)
		
class ApplicationsPageView(AbstractCommonPageView):
	def __init__(self, widgetTree):
		AbstractCommonPageView.__init__(self,widgetTree, 'ApplicationsLeftBox1', 'ApplicationsRightBox1', 'applications.menu')
		
class SettingsPageView(AbstractCommonPageView):
	def __init__(self, widgetTree):
		AbstractCommonPageView.__init__(self,widgetTree, 'SettingsLeftBox1', 'SettingsRightBox1', 'settings.menu')
		
class MainNoteBookView:
	def __init__(self, noteBook, widgetTree):
		self.noteBook = noteBook
		self.widgetTree = widgetTree
		
		noteBook.connect('switch-page', self.pageChanged)
		self.currentPageIndex = 0
		self.text = ''
		
		self.pages = [
			('Applications', ApplicationsPageView(widgetTree)), 
			('Settings', SettingsPageView(widgetTree)) ]
			
		uspCoreUtils.setNameToTabs(noteBook, [pageName for (pageName, page) in self.pages])

	def initializePages(self):
		for (name, page) in self.pages:
			page.fill()
	
	def clearPages(self):
		for (name, page) in self.pages:
			page.clear()
	
	def updatePages(self, text):
		self.text = text
		(name, page) = self.pages[self.currentPageIndex]
		page.update(text)
	
	def pageChanged(self, notebook, page, pageIndex):
		self.currentPageIndex = pageIndex
		self.updatePages(self.text)
	
	def getEvents(self):
		return {}
		
class ApplicationsView(object):
	def __init__(self, widgetTree, mainWindow, mainEventWindow):
		self.widgetTree = widgetTree
		self.mainWindow = mainWindow
		self.mainEventWindow = mainEventWindow
		
		#TransparencyUtils.opacifyWidget(self.widgetTree.get_widget("SubApplicationsLeftBox1"), 0.8)
		#TransparencyUtils.opacifyWidget(self.widgetTree.get_widget("SubApplicationsRightBox1"), 0.8)
		#TransparencyUtils.opacifyWidget(self.widgetTree.get_widget("ApplicationsLeftBox1"), 0.8)
		#TransparencyUtils.opacifyWidget(self.widgetTree.get_widget("ApplicationsRightBox1"), 0.8)
		#TransparencyUtils.opacifyWidget(self.widgetTree.get_widget("SubSettingsLeftBox1"), 0.8)
		#TransparencyUtils.opacifyWidget(self.widgetTree.get_widget("SubSettingsRightBox1"), 0.8)
		#TransparencyUtils.opacifyWidget(self.widgetTree.get_widget("SettingsLeftBox1"), 0.8)
		#TransparencyUtils.opacifyWidget(self.widgetTree.get_widget("SettingsRightBox1"), 0.8)
		
		
		noteBook = self.widgetTree.get_widget("MainNoteBook1")
		self.mainNoteBookView = MainNoteBookView(noteBook, widgetTree)
		
		allEvents = { "on_MainEventBox_button_press_event" : self.inPluginClicked }
		allEvents.update(self.mainNoteBookView.getEvents())
		
		self.widgetTree.signal_autoconnect(allEvents)
		
		self.mainNoteBookView.initializePages()
	
	def filterEntryChanged(self, text):
		self.mainNoteBookView.updatePages(text)
	
	def inPluginClicked(self, widget, event):
		pass
	
	def onRefreshButtonClicked(self, widget):
		self.mainNoteBookView.clearPages()
		self.mainNoteBookView.initializePages()
		

class Configuration(uspCoreUtils.Singleton):
	def __init__(self):
		uspCoreUtils.Singleton.__init__(self)
	
	def hideView(self):
		if self.applicationsGClient.getBoolean('hide_on_application_start', True):
			self.applicationsMainWidget.hideView()

class UspPlugin(object):
	
	gladeFilename = "applications.glade"
	
	def __init__(self):
		self.gladefile = os.path.join(os.path.dirname(__file__) , self.gladeFilename)
		
		if not os.path.exists(self.gladefile):
			raise Exception("Glade file '"+ self.gladeFilename +"' does not exist.")
			
		self.widgetTree = gtk.glade.XML(self.gladefile, "MainWindow")
		self.window = self.widgetTree.get_widget("MainWindow")
		self.contentHolder = self.widgetTree.get_widget("MainEventBox")
		
		self.gClient = uspGConfig.GConfigurator('/apps/usp2/plugins/applications')
		Configuration().applicationsGClient = self.gClient
		Configuration().applicationsMainWidget = self
		
		self.applicationView = ApplicationsView(self.widgetTree, self.window, self.contentHolder)
	
	def getPluginSize(self):
		width = self.gClient.getInteger('width', 500)
		height = self.gClient.getInteger('height', 250)
		return width, height
	
	def setPluginSize(self, width, height):
		self.gClient.setInteger('width', width)
		self.gClient.setInteger('height', height)
	
	def hideView(self):
		if hasattr(self, "configuration"):
			self.configuration.hide()
	
	def pluginName(self):
		return "Applications"
	
	def mainWidget(self):
		return self.contentHolder
	
	def pluginIcon(self):
		return 'package_settings'
	
	def filterEntryChanged(self, text):
		self.applicationView.filterEntryChanged(text)
